home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xgrabsc / xgrabsc.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  22KB  |  929 lines

  1. /*========================================================================
  2.  *
  3.  * Name - xgrabsc.c
  4.  *
  5.  * ccs version:    1.31
  6.  *
  7.  * ccsid:    @(#)xgrabsc.c    1.31 - 06/28/93 09:13:50
  8.  * from:     ccs/s.xgrabsc.c
  9.  * date:     06/28/93 09:14:49
  10.  *
  11.  * Copyright (c) 1990-93 Bruce Schuchardt.
  12.  * Read the file cpyright.h for full copyright information.
  13.  *
  14.  * XmuClientWindow and TryChildren are Copyright 1989 by the Massachusetts
  15.  * Institute of Technology
  16.  *
  17.  * Permission to use, copy, modify, and distribute this [XmuClientWindow]
  18.  * software and its
  19.  * documentation for any purpose and without fee is hereby granted, provided 
  20.  * that the above copyright notice appear in all copies and that both that 
  21.  * copyright notice and this permission notice appear in supporting 
  22.  * documentation, and that the name of M.I.T. not be used in advertising
  23.  * or publicity pertaining to distribution of the software without specific, 
  24.  * written prior permission. M.I.T. makes no representations about the 
  25.  * suitability of this software for any purpose.  It is provided "as is"
  26.  * without express or implied warranty.
  27.  *
  28.  * Description:
  29.  *
  30.  * xgrabsc - grab screen images and store in files
  31.  *
  32.  *========================================================================
  33.  */
  34.  
  35. #if defined(__hpux)
  36. /* the folks at HP have decided to make things more difficult
  37.  */
  38. #define XLIB_ILLEGAL_ACCESS
  39. #endif
  40.  
  41.  
  42. #include "cpyright.h"
  43. #include "patchlevel.h"
  44. #include "config.h"
  45. #include "checkvm.h"
  46. #include "cmdopts.h"
  47.  
  48. #include <stdio.h>
  49.  
  50. #include <X11/Xos.h>
  51. #include <X11/Xlib.h>
  52. #include <X11/Xutil.h>
  53. #include <X11/cursorfont.h>
  54. #include <X11/Xatom.h>
  55.  
  56. #ifdef VMS
  57. #include "XWDFile.h"
  58. #else
  59. #include <X11/XWDFile.h>
  60. #endif /* VMS */
  61.  
  62. #ifndef CARD32
  63. #include <X11/Xmd.h>
  64. #endif
  65.  
  66.  
  67. #ifndef NO_VIRTUAL_WINDOW
  68. #include "virtual.h"
  69. #endif
  70.  
  71.  
  72. #define MAX_CELLS  256
  73. #define TRUE  1
  74. #define FALSE 0
  75.  
  76.  
  77. typedef enum {
  78.   NO_DITHER=0,
  79.   FS_DITHER,
  80.   MATRIX_DITHER,
  81.   MATRIX_HALFTONE,
  82.   MAP_BW
  83. } ditherType;
  84.  
  85.  
  86. typedef unsigned char byte;
  87. typedef unsigned long dw;
  88. typedef unsigned int  word;
  89.  
  90.  
  91.  
  92. typedef struct {
  93.   XImage *ximage;
  94.   word numcells;
  95.   word red[MAX_CELLS], green[MAX_CELLS], blue[MAX_CELLS];
  96.   byte used[MAX_CELLS];
  97. } imageInfo;
  98.  
  99.  
  100. typedef enum {
  101.   sourceRect,
  102.   sourceRoot,
  103.   sourceId,
  104.   sourceWd,
  105.   sourceKey,
  106.   sourceCoords
  107. } sourceType;
  108.  
  109. typedef enum {
  110.   puzzleFormat,
  111.   psFormat,
  112.   simpleFormat,
  113.   xwdFormat,
  114.   pixmapFormat
  115. } formatType;
  116.  
  117.  
  118.  
  119.  
  120. #ifdef BCOPY
  121. #ifdef MEMCPY
  122. #undef MEMCPY
  123. #endif
  124. #define memcpy(x,y,c) bcopy(y,x,c)
  125. #define memset(x,c)   bzero(x,c) /* well, I only use it for zeroing out stuff */
  126. #endif
  127.  
  128. #ifdef MEMCPY
  129. char *memcpy();
  130. char *memset();
  131. #endif
  132.  
  133.  
  134. #ifdef VMS
  135. #define rindex strrchr
  136. #endif
  137.  
  138. static Display *hDisplay;
  139. static int      hScreen;
  140. static Window   hRoot, vRoot;
  141. static int      displayCells;
  142. static char    *programName;
  143. static char    imageName[64];
  144.  
  145. static char    *version    = XGRABSC_VERSION;
  146. static int      patchLevel = XGRABSC_PATCHLEVEL;
  147. static int      verbose;
  148.  
  149. static word nr[MAX_CELLS], ng[MAX_CELLS], nb[MAX_CELLS];
  150.  
  151. static char   hexdigits[] = "0123456789abcdef";
  152.  
  153. static double pageWidth   = PAPER_WIDTH;
  154. static double pageHeight  = PAPER_HEIGHT;
  155. static double horizMargin = HORIZ_MARGIN;
  156. static double vertMargin  = VERT_MARGIN;
  157. static double horizInset  = PAPER_WIDTH - HORIZ_MARGIN - HORIZ_MARGIN;
  158. static double vertInset   = PAPER_HEIGHT - VERT_MARGIN - VERT_MARGIN;
  159.  
  160. static char        *outfileName;
  161.  
  162. ditherType  DitherKind;
  163. int         Halftone;
  164. int         ForceBitmap;
  165.  
  166. static int needColorImageProc;
  167.  
  168.  
  169. /* most functions have been moved to seperate source include files */
  170.  
  171. #include "process.hc"         /* color processing     */
  172. #include "get.hc"             /* get images           */
  173. #include "mem.hc"             /* memcpy, memset       */
  174. #include "convert.hc"         /* color->bw conversion */
  175. #include "write.hc"           /* output functions     */
  176.  
  177.  
  178.  
  179.  
  180. static Window xgTryChildren();
  181.  
  182. /* versions of XmuGetClientWindow and screenNumberOfScreen.
  183.  * GetClientWindow is used so Xmu need not be linked (causes problems on
  184.  *  some platforms and configurations if Xt is not used)
  185.  * ScreenNumberOfScreen is used because some X implementations do not
  186.  *  include this function (HP in particular).
  187.  *
  188.  * The following three functions are from the X11R4 MIT distribution and
  189.  * are copyrighted by MIT (see the file header)
  190.  */
  191.  
  192. static Window GetClientWindow (win)
  193.     Window win;
  194. {
  195.     Atom WM_STATE;
  196.     Atom type = None;
  197.     int format;
  198.     unsigned long nitems, after;
  199.     unsigned char *data;
  200.     Window inf;
  201.  
  202.     WM_STATE = XInternAtom(hDisplay, "WM_STATE", True);
  203.     if (!WM_STATE)
  204.     return win;
  205.     XGetWindowProperty(hDisplay, win, WM_STATE, 0, 0, False, AnyPropertyType,
  206.                &type, &format, &nitems, &after, &data);
  207.     if (type)
  208.     return win;
  209.     inf = xgTryChildren(win, WM_STATE);
  210.     if (!inf)
  211.     inf = win;
  212.     return inf;
  213. }
  214.  
  215. static Window xgTryChildren (win, WM_STATE)
  216.     Window win;
  217.     Atom WM_STATE;
  218. {
  219.     Window root, parent;
  220.     Window *children;
  221.     unsigned int nchildren;
  222.     unsigned int i;
  223.     Atom type = None;
  224.     int format;
  225.     unsigned long nitems, after;
  226.     unsigned char *data;
  227.     Window inf = 0;
  228.  
  229.     if (!XQueryTree(hDisplay, win, &root, &parent, &children, &nchildren))
  230.     return 0;
  231.     for (i = 0; !inf && (i < nchildren); i++) {
  232.     XGetWindowProperty(hDisplay, children[i], WM_STATE, 0, 0, False,
  233.                AnyPropertyType, &type, &format, &nitems,
  234.                &after, &data);
  235.     if (type)
  236.         inf = children[i];
  237.     }
  238.     for (i = 0; !inf && (i < nchildren); i++)
  239.     inf = xgTryChildren(children[i], WM_STATE);
  240.     if (children) XFree((char *)children);
  241.     return inf;
  242. }
  243.  
  244.  
  245.  
  246. int ScreenNumberOfScreen (scr)
  247.     register Screen *scr;
  248. {
  249.     register Display *dpy = scr->display;
  250.     register Screen *dpyscr = dpy->screens;
  251.     register int i;
  252.  
  253.     for (i = 0; i < dpy->nscreens; i++, dpyscr++) {
  254.     if (scr == dpyscr) return i;
  255.     }
  256.     return -1;
  257. }
  258.  
  259.  
  260.  
  261. xgrabsc(argc, argv, env)
  262.   int argc;
  263.   char *argv[];  /* must have at least argv[0] == programName */
  264.   char *env;
  265. {
  266.   char        *args[100], *arg;
  267.   extern char *optarg;
  268.   FILE        *outfile;
  269.   XRectangle  xrect;
  270.   XWindowAttributes xwa;
  271.   imageInfo   image;
  272.   int         argn, argi, polarity;
  273.   int          cmdi, cmdargi;
  274.   int         doAnd;
  275.   int         doOr;
  276.   int         doReverse;
  277.   int         depth;
  278.   int         noBell;
  279.   int         psColor;
  280.   int         brighten;
  281.   int         grabServer;
  282.   int         compress;
  283.   int         sleepSeconds;
  284.   int         postSelectSleepSeconds;
  285.   int         andBits;
  286.   int         orBits;
  287.   int         encapsulate;
  288.   Window      sourceWindow, childWindow, clientWindow, wmWindow, ignored;
  289.   char       *ptr;
  290.   char       *display;
  291.   int         i, x, y;
  292.   int         brightenFactor;
  293.   sourceType  source;
  294.   formatType  outputFormat;
  295.   int         xpmFormat;
  296.   int         landscape;
  297.   int         binary;
  298.   int          borders;
  299.   int          checkLimits;
  300.   int          preview;
  301.   int         onlyEpsi;
  302.   int         xwdxy;
  303.  
  304.  
  305.   outfile     = stdout;
  306.   outfileName = NULL;
  307.   display     = NULL;
  308.   programName = argv[0];
  309.  
  310.   noBell       = FALSE;
  311.   brighten     = FALSE;
  312.   compress     = TRUE;
  313.   DitherKind   = NO_DITHER;
  314.   doAnd        = FALSE;
  315.   doOr         = FALSE;
  316.   doReverse    = FALSE;
  317.   encapsulate  = FALSE;
  318.   ForceBitmap  = FALSE;
  319.   grabServer   = TRUE;
  320.   Halftone     = FALSE;
  321.   landscape    = FALSE;
  322.   binary       = FALSE;
  323.   sleepSeconds = 0;
  324.   postSelectSleepSeconds = 0;
  325.   verbose      = FALSE;
  326.   borders      = TRUE;
  327. #ifdef NO_PRINTER_MEMORY_CHECKS
  328.   checkLimits  = FALSE;
  329. #else
  330.   checkLimits  = TRUE;
  331. #endif
  332.   preview      = FALSE;
  333.   needColorImageProc = DEFAULT_NEED_COLORIMAGE_PROC;
  334.  
  335.   source       = sourceRect;
  336.   outputFormat = psFormat;
  337.   psColor      = FALSE;
  338.   onlyEpsi     = FALSE;
  339.   xwdxy           = FALSE;
  340.  
  341.  
  342.   /* merge environment options and command line options */
  343.   args[0] = programName;
  344.   if (env != NULL) {
  345.     args[1] = env;
  346.     for (argn=2; argn<100  &&
  347.                 (args[argn]=(char *)strchr(args[argn-1], ' ')) != NULL;
  348.             argn++) {
  349.       /* remove leading white space */
  350.       while (*args[argn] == ' ' || *args[argn] == 9) {
  351.         *(args[argn]) = '\0';
  352.         args[argn]++;
  353.       }
  354.       if (*args[argn] == '|' || *args[argn] == '>') /* dbx leaves these in the cmd line */
  355.         break;
  356.     }
  357.   }
  358.   else
  359.     argn = 1;
  360.  
  361.   for (i=1; i<argc && argn<100; argn++, i++)
  362.     args[argn] = argv[i];
  363.  
  364.   
  365.   for (argi=1; argi<argn; argi++) {
  366.     arg = args[argi];
  367.  
  368.     polarity = 1;
  369.     if (arg[0] == '-') {
  370.       arg++;
  371.       if (arg[0] == '-') {
  372.         arg++;
  373.         polarity = 0;
  374.       }
  375.       else if (arg[0] == 'n' && arg[1] == 'o') {
  376.         arg += 2;
  377.     polarity = 0;
  378.       }
  379.     }
  380.  
  381.     for (cmdi=0; cmdi<numCmds; cmdi++) {
  382.       if (strcmp(arg, commands[cmdi].userstr) == 0)
  383.         break;
  384.     }
  385.     if (cmdi >= numCmds) {
  386.       fprintf(stderr, "%s: unknown option '%s'\n", programName, arg);
  387.       exit(3);
  388.     }
  389.  
  390.     cmdargi = argi+1;
  391.     argi += commands[cmdi].numargs;
  392.     if (argi >= argn) {
  393.       fprintf(stderr, "%s: not enough arguments for '%s'\n", programName, arg);
  394.       exit(3);
  395.     }
  396.  
  397.     switch (commands[cmdi].command) {
  398.       case CMD_DISPLAY:
  399.         display = args[cmdargi];
  400.         break;
  401.       case CMD_BELL:
  402.         noBell = !polarity;
  403.         break;
  404.       case CMD_GRABSERVER:
  405.         grabServer = polarity;
  406.         break;
  407.       case CMD_OUTPUT:
  408.         outfileName = args[cmdargi];
  409.         break;
  410.       case CMD_PRESLEEP:
  411.         sleepSeconds = atoi(args[cmdargi]);
  412.         if (sleepSeconds < 0) sleepSeconds = 0;
  413.         break;
  414.       case CMD_POSTSLEEP:
  415.         postSelectSleepSeconds = atoi(args[cmdargi]);
  416.         if (postSelectSleepSeconds < 0) postSelectSleepSeconds = 0;
  417.         break;
  418.       case CMD_VERBOSE:
  419.         verbose = polarity;
  420.         break;
  421.       case CMD_BORDERS:
  422.         borders = polarity;
  423.     break;
  424.       case CMD_NOBORDERS:
  425.         borders = !polarity;
  426.     break;
  427.  
  428.  
  429.       case CMD_SOURCE_KEY:
  430.         source = sourceKey;
  431.         grabServer = FALSE;
  432.     break;
  433.       case CMD_SOURCE_COORDS:
  434.       { short w,h,x,y;
  435.     source = sourceCoords;
  436.         sscanf(args[cmdargi], "%ix%i+%i+%i", &w, &h, &x, &y);
  437.     xrect.width = w; 
  438.     xrect.height = h;
  439.     xrect.x = x;  
  440.     xrect.y = y;
  441.     break;
  442.       }
  443.  
  444.       case CMD_SOURCE_ID:
  445.         source = sourceId;
  446.         sourceWindow = 0;
  447.         if (!sscanf(args[cmdargi], "%ix", &sourceWindow)) {
  448.           fprintf(stderr, "%s: invalid window id '%s'\n", programName, args[cmdargi]);
  449.       exit(3);
  450.         }
  451.         break;
  452.       case CMD_SOURCE_RECT:
  453.     source = sourceRect;
  454.     break;
  455.       case CMD_SOURCE_ROOT:
  456.         source = sourceRoot;
  457.         break;
  458.       case CMD_SOURCE_WD:
  459.         source = sourceWd;
  460.         break;
  461.  
  462.  
  463.  
  464.       case CMD_AND:
  465.         doAnd = polarity;
  466.     if (doAnd)
  467.           andBits = atoi(args[cmdargi]);
  468.         break;
  469.       case CMD_OR:
  470.         doOr = polarity;
  471.     if (doOr)
  472.           orBits = atoi(args[cmdargi]);
  473.         break;
  474.       case CMD_NOT:
  475.         doReverse = polarity;
  476.     break;
  477.       case CMD_BRIGHTEN:
  478.         brighten = polarity;
  479.     if (brighten) {
  480.           brightenFactor = atoi(args[cmdargi]);
  481.           if (brightenFactor <= 0) {
  482.             fprintf(stderr, "%s: brightening factor must be a positive number\n",
  483.               programName);
  484.             exit(3);
  485.           }
  486.       if (brightenFactor != 100)
  487.             brighten = TRUE;
  488.       else
  489.         brighten = FALSE;
  490.     }
  491.         break;
  492.  
  493.       case CMD_DITHER_MAP:
  494.         ForceBitmap = TRUE;
  495.         Halftone = FALSE;
  496.         break;
  497.       case CMD_DITHER_MATRIX:
  498.         DitherKind = MATRIX_DITHER;
  499.         Halftone = TRUE;
  500.         ForceBitmap = FALSE;
  501.         break;
  502.       case CMD_DITHER_FS:
  503.         if (!polarity) {
  504.           DitherKind = NO_DITHER;
  505.       Halftone = ForceBitmap = FALSE;
  506.         }
  507.         else {
  508.           DitherKind = FS_DITHER;
  509.           Halftone = TRUE;
  510.           ForceBitmap = FALSE;
  511.         }
  512.         break;
  513.       case CMD_DITHER_HALFTONE:
  514.         DitherKind = MATRIX_HALFTONE;
  515.         Halftone = TRUE;
  516.         ForceBitmap = FALSE;
  517.         break;
  518.       case CMD_DITHER_NONE:
  519.         DitherKind = NO_DITHER;
  520.     Halftone = ForceBitmap = FALSE;
  521.     break;
  522.  
  523.  
  524.  
  525.       case CMD_OUTPUT_PS:
  526.         psColor = FALSE;
  527.         outputFormat = psFormat;
  528.         break;
  529.       case CMD_OUTPUT_CPS:
  530.         psColor = polarity;
  531.         outputFormat = psFormat;
  532.     break;
  533.       case CMD_OUTPUT_SIMPLE:
  534.         outputFormat = simpleFormat;
  535.         break;
  536.       case CMD_OUTPUT_XWD:
  537.         outputFormat = xwdFormat;
  538.     xwdxy = FALSE;
  539.         break;
  540.       case CMD_OUTPUT_XWDXY:
  541.         outputFormat = xwdFormat;
  542.     xwdxy = TRUE;
  543.         break;
  544.       case CMD_OUTPUT_PIXMAP:
  545.         xpmFormat = 1;
  546.         outputFormat = pixmapFormat;
  547.         break;
  548.       case CMD_OUTPUT_XPM2:
  549.         if (polarity) xpmFormat = 2;
  550.     else if (xpmFormat == 2) xpmFormat = 1;
  551.     outputFormat = pixmapFormat;
  552.     break;
  553.       case CMD_OUTPUT_XPM3:
  554.         if (polarity) xpmFormat = 3;
  555.     else if (xpmFormat == 3) xpmFormat = 1;
  556.     outputFormat = pixmapFormat;
  557.     break;
  558.  
  559.       case CMD_OUTPUT_PUZZLE:
  560.         outputFormat = puzzleFormat;
  561.         break;
  562.  
  563.       case CMD_LANDSCAPE:
  564.         landscape = polarity;
  565.     outputFormat = psFormat;
  566.         break;
  567.       case CMD_BIN:
  568.         binary = polarity;
  569.         outputFormat = psFormat;
  570.     break;
  571.       case CMD_COMPRESS:
  572.         compress = polarity;
  573.         outputFormat = psFormat;
  574.         break;
  575.       case CMD_EPS:
  576.         encapsulate = polarity;
  577.         outputFormat = psFormat;
  578.     break;
  579.       case CMD_PREVIEWONLY:
  580.         onlyEpsi = polarity;
  581.     preview = polarity;
  582.         outputFormat = psFormat;
  583.     break;
  584.       case CMD_LIMIT:
  585.         checkLimits = polarity;
  586.         outputFormat = psFormat;
  587.     break;
  588.       case CMD_PREVIEW:
  589.         preview = polarity;
  590.         outputFormat = psFormat;
  591.     break;  
  592.       case CMD_PAGE:
  593.         outputFormat = psFormat;
  594.         sscanf(args[cmdargi], "%lfx%lf-%lf-%lf",
  595.       &pageWidth, &pageHeight, &horizMargin, &vertMargin);
  596.     horizInset = pageWidth - horizMargin - horizMargin;
  597.     vertInset  = pageHeight - vertMargin - vertMargin;
  598.         break;
  599.       case CMD_COLORPROC:
  600.         outputFormat = psFormat;
  601.     needColorImageProc = polarity;
  602.     break;
  603.     }
  604.   }
  605.  
  606.  
  607.   if (verbose) {
  608.     fprintf(stderr, "%s: xgrabsc version %s\n", programName, version);
  609.     fprintf(stderr, "%s:         patchlevel %d\n", programName, patchLevel);
  610.     fprintf(stderr, "%s:         %s\n\n", programName, Copyright);
  611.   }
  612.  
  613.   if (!display) display = (char *)getenv("DISPLAY");
  614.   hDisplay = XOpenDisplay(display);
  615.   if (!hDisplay) {
  616.     fprintf(stderr, "%s: could not open X display\n", programName);
  617.     exit(3);
  618.   }
  619.   hScreen  = DefaultScreen(hDisplay);
  620.   hRoot    = DefaultRootWindow(hDisplay);
  621. #ifndef NO_VIRTUAL_WINDOW
  622.   vRoot    = VirtualRootWindow(hDisplay, hScreen);
  623. #else
  624.   vRoot    = hRoot;
  625. #endif
  626.  
  627.   depth  = DefaultDepth(hDisplay, hScreen);
  628.   if (DisplayCells(hDisplay, hScreen) > MAX_CELLS) {
  629.     fprintf(stderr, "%s: color table is too big for this program\n",
  630.       programName);
  631.     XCloseDisplay(hDisplay);
  632.     exit(3);
  633.   }
  634.  
  635.   /* sleep if asked to do so */
  636.   if (sleepSeconds)
  637.     sleep(sleepSeconds);
  638.  
  639.   /* grab the screen if asked to do so */
  640.   if (grabServer)
  641.     XGrabServer(hDisplay);
  642.  
  643.   if (source != sourceId)
  644.     sourceWindow = hRoot;
  645.  
  646.   childWindow = (Window)NULL;
  647.  
  648.   switch (source) {
  649.     case sourceKey:
  650.       childWindow =
  651. #ifdef SELECTION_MASK
  652.           getWindowWhenKeyIsPressed(SELECTION_MASK)
  653. #else
  654.           getWindowWhenKeyIsPressed(ControlMask);
  655. #endif
  656.       if (!childWindow) {
  657.         fprintf(stderr, "%s: unable to find source window\n", programName);
  658.         XCloseDisplay(hDisplay);
  659.         exit(3);
  660.       }
  661.       break;
  662.     case sourceCoords:
  663.       /* already got the xrect in the command line processing section */
  664.       break;
  665.     case sourceId:
  666.       childWindow = sourceWindow;
  667.       break;
  668.     case sourceWd:
  669.       /* grab the image from the root window so menus will show up on top
  670.        * of the window */
  671.       childWindow=getWindow();
  672.       if (!childWindow) {
  673.         fprintf(stderr, "%s: unable to find source window\n", programName);
  674.         XCloseDisplay(hDisplay);
  675.         exit(3);
  676.       }
  677.       break;
  678.     case sourceRoot:
  679.       xrect.x = xrect.y = 0;
  680.       xrect.width  = DisplayWidth(hDisplay, hScreen);
  681.       xrect.height = DisplayHeight(hDisplay, hScreen);
  682.       break;
  683.     case sourceRect:
  684.     default:
  685.       if (!getRectangle(&xrect)) {
  686.         XCloseDisplay(hDisplay);
  687.         exit(3);
  688.       }
  689.       break;
  690.   }
  691.  
  692.  
  693.  
  694.   clientWindow = (Window)NULL;
  695.   if (!borders  &&
  696.       (source == sourceKey || source == sourceWd || source == sourceId)  &&
  697.       childWindow != hRoot) {
  698.     /* look for a different client window */
  699.     clientWindow = GetClientWindow(childWindow);
  700.     if (clientWindow && clientWindow != childWindow) {
  701.       if (verbose)
  702.     fprintf(stderr, "%s: found subwindow 0x%x\n", programName, clientWindow);
  703.       wmWindow = childWindow;
  704.       childWindow = clientWindow;
  705.     }
  706.   }
  707.  
  708.   if ((source == sourceKey && childWindow != hRoot) ||
  709.       source == sourceId ||
  710.       source == sourceWd) {
  711.  
  712.     if (childWindow == hRoot) {
  713.       xrect.x      = 0;
  714.       xrect.y      = 0;
  715.       xrect.width  = DisplayWidth(hDisplay, hScreen);
  716.       xrect.height = DisplayHeight(hDisplay, hScreen);
  717.     }
  718.     else {
  719.  
  720.       /* take the child window (and optional client/wm window info) and
  721.       * determine the portion of the root window that should be grabbed */
  722.  
  723.       if (!XGetWindowAttributes(hDisplay, childWindow, &xwa)) {
  724.         fprintf(stderr, "%s: unable to get window coordinates\n", programName);
  725.         XCloseDisplay(hDisplay);
  726.         exit(3);
  727.       }
  728.  
  729.       /* get the correct screen and root window for the selected window,
  730.         * and if it isn't the default, muck with the global state of the
  731.         * program a bit
  732.         */
  733.       i = ScreenNumberOfScreen(xwa.screen);
  734.       if (i != hScreen) {
  735.         hRoot   = xwa.root;
  736.         hScreen = i;
  737. #ifndef NO_VIRTUAL_WINDOW
  738.         vRoot   = VirtualRootWindow(hDisplay, hScreen);
  739. #else
  740.         vRoot   = hRoot;
  741. #endif
  742.         depth   = DefaultDepth(hDisplay, hScreen);
  743.       }
  744.  
  745.       sourceWindow = vRoot;
  746.       if (!borders) {
  747.         xrect.x      = 0;
  748.         xrect.y      = 0;
  749.         xrect.width  = xwa.width;
  750.         xrect.height = xwa.height;
  751.       }
  752.       else {
  753.         xrect.x      = -xwa.border_width;
  754.         xrect.y      = -xwa.border_width;
  755.         xrect.width  = xwa.width + (2 * xwa.border_width);
  756.         xrect.height = xwa.height + (2 * xwa.border_width);
  757.       }
  758.  
  759.       /* translate the rectangle coordinates to root-window coordinates */
  760.       if (!XTranslateCoordinates(hDisplay, childWindow, vRoot,
  761.             (int)(xrect.x), (int)(xrect.y), &x, &y, &ignored)) {
  762.     fprintf(stderr, "%s: unable to translate window coordinates\n", programName);
  763.     XCloseDisplay(hDisplay);
  764.     exit(3);
  765.       }
  766.       xrect.x = (short)x;   /* why did they make rectangle coords shorts? */
  767.       xrect.y = (short)y;
  768.  
  769.  
  770.       if (hRoot == vRoot) {
  771.         /* do some clipping here, since it's cheap */
  772.         i = DisplayWidth(hDisplay, hScreen);
  773.         if (xrect.x + xrect.width > i) {
  774.           x = i - (int)(xrect.x);
  775.           if (x < 0) x = 0;
  776.           xrect.width = x;
  777.         }
  778.         i = DisplayHeight(hDisplay, hScreen);
  779.         if (xrect.y + xrect.height > i) {
  780.           x = i - (int)(xrect.y);
  781.           if (x < 0) x = 0;
  782.           xrect.height = x;
  783.         }
  784.       }
  785.     }
  786.   }
  787.  
  788.  
  789.   if (verbose)
  790.     fprintf(stderr, "%s: bounding box is [x=%d y=%d w=%d h=%d]\n", programName, xrect.x, xrect.y,
  791.                     xrect.width, xrect.height);
  792.  
  793.   /* sleep if asked to do so */
  794.   if (postSelectSleepSeconds) {
  795.     if (grabServer) {
  796.       XUngrabServer(hDisplay);
  797.       XSync(hDisplay, FALSE);
  798.     }
  799.     sleep(postSelectSleepSeconds);
  800.     if (grabServer)
  801.       XGrabServer(hDisplay);
  802.   }
  803.  
  804.  
  805.   /* get the image bounded by the rectangle from the source window */
  806.   if (!noBell)
  807.     XBell(hDisplay, 50);
  808.  
  809.   if (!getImage(&xrect, &image, sourceWindow, childWindow)) {
  810.     XCloseDisplay(hDisplay);
  811.     exit(3);
  812.   }
  813.   if (grabServer)
  814.     XUngrabServer(hDisplay);
  815.  
  816.   if (!noBell) {
  817.     XBell(hDisplay, 20);
  818.     XBell(hDisplay, 30);
  819.   }
  820.  
  821.   XFlush(hDisplay);
  822.  
  823.  
  824.  
  825.   /* do color image processing/conversions */
  826.  
  827.   if (depth >= 2) {
  828.     if (brighten)
  829.       brightenColors(&image, brightenFactor);
  830.     if (doAnd)
  831.       alterPlanes(&image, TRUE, andBits);
  832.     if (doOr)
  833.       alterPlanes(&image, FALSE, orBits);
  834.   }
  835.   
  836.   if (doReverse)
  837.     reverseColors(&image);
  838.  
  839.   if (depth >= 2) {
  840.     if (! (preview && psColor) ) {
  841.       if (ForceBitmap) {
  842.         pixmap2bitmap(&image);
  843.         depth = 1;
  844.       }
  845.       else if (Halftone)
  846.         pixmap2halftone(&image, DitherKind);
  847.       else
  848.         compressColormap(&image);
  849.     }
  850.     else
  851.       compressColormap(&image);
  852.   }
  853.  
  854.  
  855.   /* open the output stream */
  856.   if (outfileName) {
  857.     outfile = fopen(outfileName, "w");
  858.     if (!outfile) {
  859.       fprintf(stderr, "%s: ", programName);
  860.       perror(outfileName);
  861.       exit(3);
  862.     }
  863.     /* form an image name based on the file name */
  864.     {
  865.     char *img = rindex(outfileName, '/');
  866.     if (img) strcpy(imageName, img + 1);
  867.     else strcpy(imageName, outfileName);
  868.     ptr = rindex(imageName, '.');  /* Drop the final extension */
  869.     if (ptr) *ptr = '\0';
  870.     }
  871.   }
  872.   else
  873.     strcpy(imageName,"unnamed");
  874.  
  875.  
  876.   /* write to the output stream in the requested format */
  877.   switch (outputFormat) {
  878.     case xwdFormat:
  879.       writeXWD(&image, outfile, xwdxy);
  880.       break;
  881.     case simpleFormat:
  882.       writeSimple(&image, outfile);
  883.       break;
  884.     case puzzleFormat:
  885.       writePuzzle(&image, outfile);
  886.       break;
  887.     case pixmapFormat:
  888.       if (image.ximage->depth <= 1)
  889.         writeXYPixmap(&image, outfile);
  890.       else
  891.         writeZPixmap(xpmFormat, &image, outfile);
  892.       break;
  893.     case psFormat:
  894.     default:
  895.       if (onlyEpsi)
  896.         writeOnlyPreview(&image, outfile);
  897.       else if (psColor && image.ximage->depth >= 2)
  898.         writeColorPS(&image, outfile, compress, encapsulate,
  899.                     preview, landscape, binary, checkLimits);
  900.       else
  901.         writePostscript(&image, outfile, compress, encapsulate,
  902.                     preview, landscape, binary, checkLimits);
  903.       break;
  904.   }
  905.  
  906.  
  907.   XDestroyImage(image.ximage);
  908.   XCloseDisplay(hDisplay);
  909.   if (outfileName)
  910.     fclose(outfile);
  911.  
  912.   exit(0);
  913. }
  914.  
  915.  
  916.  
  917.  
  918.  
  919. #ifndef NO_MAIN
  920. main(argc, argv)
  921.   int argc;
  922.   char *argv[];
  923. {
  924.   char *env;
  925.   env = (char *)getenv("XGRABSC");
  926.   xgrabsc(argc, argv, env);
  927. }
  928. #endif
  929.